﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Xml;

namespace Common.XmlHandle
{
    public class XmlBrigade
    {
        private XmlDocument xdoc;
        private string xmlPath = null;
        private static XmlNode root = null;
        private List<ClassBrigade> list = new List<ClassBrigade>();
        static ReaderWriterLockSlim lockSlim = new ReaderWriterLockSlim();

        public XmlBrigade(string path)
        {
            xmlPath = path;
            try
            {
                xdoc = new XmlDocument();
                xdoc.Load(path);
                root = xdoc.SelectSingleNode("Polices");
            }
            catch (DirectoryNotFoundException)
            {
                Directory.CreateDirectory(path.Substring(0, path.LastIndexOf(@"\")));
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement("Polices"));
                root = xdoc.SelectSingleNode("Polices");
                xdoc.Save(path);
            }
            catch (FileNotFoundException)
            {
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement("Polices"));
                root = xdoc.SelectSingleNode("Polices");
                xdoc.Save(path);
            }
            catch (XmlException)
            {
                xdoc = new XmlDocument();
                XmlDeclaration dec = xdoc.CreateXmlDeclaration("1.0", "utf-8", null);
                xdoc.AppendChild(dec);
                xdoc.AppendChild(xdoc.CreateElement("Polices"));
                root = xdoc.SelectSingleNode("Polices");
                xdoc.Save(path);
            }
            catch
            {
                throw;
            }
        }
        
        public List<ClassBrigade> GetAll()
        {
            lockSlim.EnterReadLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList xlist = root.ChildNodes;
            List<ClassBrigade> brigadeList = new List<ClassBrigade>();
            foreach (XmlNode node in xlist)
            {
                brigadeList.Add(GetBrigadeFromNode(node));
            }
            list = brigadeList;
            lockSlim.ExitReadLock();
            return list;
        }

        public long GetFileSize()
        {
            FileInfo f = new FileInfo(xmlPath);
            return f.Length;
        }

        public bool IsDefindFullname(string fullName)
        {
            lockSlim.EnterReadLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodes = root.ChildNodes;
            foreach (XmlNode node in nodes)
            {
                XmlNodeList eles = node.ChildNodes;
                if (eles[4].InnerText.Equals(fullName))
                {
                    lockSlim.ExitReadLock();
                    return true;
                }
            }
            lockSlim.ExitReadLock();
            return false;
        }

        public bool IsDefindCode(string code)
        {
            lockSlim.EnterReadLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                XmlNodeList eles = node.ChildNodes;
                if (eles[5].InnerText.Equals(code))
                {
                    lockSlim.ExitReadLock();
                    return true;
                }
            }
            lockSlim.ExitReadLock();
            return false;
        }

        public ClassBrigade GetBrigadeByGuid(Guid guid)
        {
            lockSlim.EnterReadLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodes = root.ChildNodes;
            foreach(XmlNode node in nodes)
            {
                XmlElement nod = node as XmlElement;
                Guid uid = new Guid(nod.GetAttribute("Guid"));
                if (uid.Equals(guid))
                {
                    lockSlim.ExitReadLock();
                    return GetBrigadeFromNode(node);
                }
            }
            lockSlim.ExitReadLock();
            return null;
        }

        public void AddBrigade(ClassBrigade newBrigade)
        {
            lockSlim.EnterWriteLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodees = root.ChildNodes;
            foreach (XmlNode nodee in nodees)
            {
                XmlElement nod = (XmlElement)nodee;
                if (nod.GetAttribute("Guid").Equals(newBrigade.Guid.ToString()))
                {
                    EditNode(nodee, newBrigade);
                    xdoc.Save(xmlPath);
                    lockSlim.ExitWriteLock();
                    return;
                }
            }
            AddElement2Node(root, newBrigade);
            xdoc.Save(xmlPath);
            lockSlim.ExitWriteLock();
        }

        public void EditBrigade(ClassBrigade newBrigade)
        {
            lockSlim.EnterWriteLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodees = root.ChildNodes;
            foreach (XmlNode nodee in nodees)
            {
                XmlElement nod = (XmlElement)nodee;
                if (nod.GetAttribute("Guid") == newBrigade.Guid.ToString())
                {
                    EditNode(nodee, newBrigade);
                    xdoc.Save(xmlPath);
                    return;
                }
            }
            xdoc.Save(xmlPath);
            lockSlim.ExitWriteLock();
        }

        public void RemoveBrigade(ClassBrigade classBrigade)
        {
            lockSlim.EnterWriteLock();
            //xdoc.Load(xmlPath);
            //root = xdoc.SelectSingleNode("Polices");
            XmlNodeList nodees = root.ChildNodes;
            foreach (XmlNode nodee in nodees)
            {
                XmlElement nod = (XmlElement)nodee;
                if (nod.GetAttribute("Guid").Equals(classBrigade.Guid))
                {
                    nodee.ParentNode.RemoveChild(nodee);
                    xdoc.Save(xmlPath);
                    return;
                }
            }
            lockSlim.ExitWriteLock();
        }
        ////////////////////////////////////////////
        ////////////////基础操作方法////////////////
        ////////////////////////////////////////////
        private void AddElement2Node(XmlNode root, ClassBrigade brigade)
        {
            XmlElement node = xdoc.CreateElement("Police");
            node.SetAttribute("Guid", brigade.Guid.ToString());
            XmlElement ele = xdoc.CreateElement("FullName");
            ele.InnerText = brigade.FullName;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("Province");
            ele.InnerText = brigade.Province;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("City");
            ele.InnerText = brigade.City;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("District");
            ele.InnerText = brigade.District;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("Brigade");
            ele.InnerText = brigade.Brigade;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("Code");
            ele.InnerText = brigade.Code;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("Address");
            ele.InnerText = brigade.Address;
            node.AppendChild(ele);
            ele = xdoc.CreateElement("Postcode");
            ele.InnerText = brigade.Postcode;
            node.AppendChild(ele);
            root.AppendChild(node);
        }

        private void EditNode(XmlNode node, ClassBrigade brigade)
        {
            XmlElement nod = (XmlElement)node;
            XmlNodeList eles = nod.ChildNodes;
            foreach(XmlNode ele in eles)
            {
                if (ele.Name.Equals("FullName"))
                {
                    ele.InnerText = brigade.FullName;
                }
                else if (ele.Name.Equals("Province"))
                {
                    ele.InnerText = brigade.Province;
                }
                else if (ele.Name.Equals("City"))
                {
                    ele.InnerText = brigade.City;
                }
                else if (ele.Name.Equals("District"))
                {
                    ele.InnerText = brigade.District;
                }
                else if (ele.Name.Equals("Brigade"))
                {
                    ele.InnerText = brigade.Brigade;
                }
                else if (ele.Name.Equals("Code"))
                {
                    ele.InnerText = brigade.Code;
                }
                else if (ele.Name.Equals("Address"))
                {
                    ele.InnerText = brigade.Address;
                }
                else if (ele.Name.Equals("Postcode"))
                {
                    ele.InnerText = brigade.Postcode;
                }
            }
        }

        private ClassBrigade GetBrigadeFromNode(XmlNode node)
        {
            ClassBrigade b = new ClassBrigade();
            XmlElement police = (XmlElement)node;
            b.Guid = new Guid(police.GetAttribute("Guid"));
            XmlNodeList nodeList = police.ChildNodes;
            b.FullName = nodeList[0].InnerText;
            b.Province = nodeList[1].InnerText;
            b.City = nodeList[2].InnerText;
            b.District = nodeList[3].InnerText;
            b.Brigade = nodeList[4].InnerText;
            b.Code = nodeList[5].InnerText;
            b.Address = nodeList[6].InnerText;
            b.Postcode = nodeList[7].InnerText;
            return b;
        }
    }
}
